package com.lry.sso.gateway.filter;

import com.lry.sso.auth.common.constant.LoginAuthorizationConstant;
import com.lry.sso.auth.common.dto.AuthConfigInfo;
import com.lry.sso.auth.common.exception.AuthException;
import com.lry.sso.auth.common.util.AuthUtil;
import com.lry.sso.auth.common.util.SessionInfo;
import com.lry.sso.common.exception.SysInvocationException;
import com.lry.sso.common.util.PathUtil;
import com.lry.sso.gateway.config.AuthConfigProperties;
import com.lry.sso.gateway.feign.AuthFeign;
import com.lry.sso.service.redis.service.RedisService;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author 李瑞益
 * @date 2020-02-17 12:13
 */
public class AuthTokenFilter extends ZuulFilter {

    private static final Logger logger = LoggerFactory.getLogger(AuthTokenFilter.class);

    @Autowired
    private AuthFeign authFeign;

    @Autowired
    private RedisService redisService;

    @Autowired
    private AuthConfigProperties authConfigProperties;

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return FilterConstants.PRE_DECORATION_FILTER_ORDER + 1;
    }

    @Override
    public boolean shouldFilter() {
        return authConfigProperties.getTokenFilter().isEnable();
    }

    @Override
    public Object run() throws ZuulException {
        HttpServletRequest request = RequestContext.getCurrentContext().getRequest();
        String token = AuthUtil.getTokenForUrl(request);

        //忽略url
        if (this.ignoreUrl(request.getRequestURI())) {
            return null;
        }
        if (token == null) {
            logger.info("无token信息");
            throw new SysInvocationException(AuthException.AUTH_FAIL);
        }
        SessionInfo sessionInfo = authFeign.parseToken(token);
        if (sessionInfo == null) {
            logger.info("token信息无效或过期");
            throw new SysInvocationException(AuthException.AUTH_FAIL);
        }
        //todo 多地登录限制，token注销 ；暂时不做

        Long expire = authFeign.getExpire(token);

        AuthConfigInfo authConfigInfo = authFeign.getAuthConfig();

        logger.info("登录的用户信息：{}",sessionInfo);

        logger.info("token过期时间剩余：{}分钟", expire / 60000.0);
        if (expire < authConfigInfo.getLoginExpire()) {
            logger.info("token过期时间小于登录过期时间，设置token过期时间为登录过期时间。");
            String newToken = authFeign.makeToken(sessionInfo);
            redisService.set(AuthUtil.getLoginJwtKey(sessionInfo.getSessionId()), newToken, authConfigInfo.getJwtExpire());

            HttpServletResponse response = RequestContext.getCurrentContext().getResponse();
            response.setHeader(LoginAuthorizationConstant.TOKEN_HEADER, newToken);
        }
        return null;
    }

    /**
     * 忽略的url
     * @param uri
     * @return
     */
    private boolean ignoreUrl(String uri){
        return PathUtil.match(uri, "/login/**");
    }
}
